package org.jeecg.modules.solitaire_app.control.utils;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.jeecg.modules.solitaire_app.annotation.SignatureValidation;
import org.jeecg.modules.solitaire_app.app.entity.YsyUsers;
import org.jeecg.modules.solitaire_app.app.service.IYsyUsersService;
import org.jeecg.modules.solitaire_app.control.entity.YsyControlKey;
import org.jeecg.modules.solitaire_app.control.service.IYsyControlKeyService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.SortedMap;

@Slf4j
@Aspect
@Component
public class SignAspect {

    @Autowired
    private IYsyControlKeyService ysyControlKeyService;

    @Before("@annotation(signatureValidation)")
    public void doBefore(SignatureValidation signatureValidation) throws Throwable {
        // 接收到请求，记录请求内容
        HttpServletRequest request = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getRequest();
        SortedMap<String, String> allParams = HttpUtils.getAllParams(request);

        // 1、获取请求参数得签名sign，
        String sign = allParams.get("sign");
        if (StrUtil.isBlank(sign)) {
            throw new RuntimeException("sign不能为空");
        }

        // 2、获取请求参数secret
        String appId = allParams.get("appId");
        if (ObjectUtil.isEmpty(appId)){
            throw new RuntimeException("appId不能为空");
        }
        YsyControlKey ysyControlKey = ysyControlKeyService.getOne(Wrappers.<YsyControlKey>lambdaQuery()
                .eq(YsyControlKey::getAppId,appId));

        if (ObjectUtil.isEmpty(ysyControlKey)){
            throw new RuntimeException("非法appId！！！");
        }

        if (ysyControlKey.getExpireTime().before(new Date())){
            throw new RuntimeException("appId已过期，请联系客服！！！");
        }

        // 3、获取请求参数timestamp 时间戳，
        String timestamp = allParams.get("timestamp");
        if (StrUtil.isBlank(timestamp)) {
            throw new RuntimeException("timestamp不能为空");
        }
        //3. 比较时间，120s内为合法请求
        if (Math.abs(Long.parseLong(timestamp) - System.currentTimeMillis()) > 120000) {
            throw new RuntimeException("timestamp失效");
        }
        verifySign(allParams,ysyControlKey);
    }

    private void verifySign(SortedMap<String, String> allParams,YsyControlKey ysyControlKey) {
        // 对方签名
        String sign = allParams.get("sign");

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("appId",ysyControlKey.getAppId());
        jsonObject.put("secret",ysyControlKey.getSecret());
        jsonObject.put("timestamp",allParams.get("timestamp"));

        String mySign = encrypt(JSONUtil.toJsonStr(jsonObject)).toUpperCase();
        log.info("验签，对方签名：{}，我方签名：{}", sign, mySign);
        // 验签
        Assert.isTrue(StrUtil.equals(sign, mySign), "验签失败");
    }

    public static String encrypt(String input) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(input.getBytes());
            byte[] digest = md.digest();

            StringBuilder sb = new StringBuilder();
            for (byte b : digest) {
                sb.append(String.format("%02x", b & 0xff));
            }
            return sb.toString();
        } catch (NoSuchAlgorithmException e) {
            // 处理异常
        }
        return null;
    }

}

